<template>
    <div class="stats" ref="statsRef"></div>
    <div class="container" ref="containerRef">
    </div>
</template>

<script setup>

import { ref, onMounted, onActivated } from 'vue'
import {
    Scene, BoxGeometry, MeshBasicMaterial, Mesh, PerspectiveCamera,
    WebGLRenderer,
    AxesHelper,
    MeshLambertMaterial,
    AmbientLight,
    PointLight,
    PointLightHelper,
    DirectionalLight, Vector2,
    Raycaster,
} from 'three'

import { OrbitControls } from 'three/examples/jsm/Addons.js'
import Stats from 'three/examples/jsm/libs/stats.module.js'

import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass.js';

// import Stats from 'stats.js'
const stats = new Stats()
stats.showPanel(0)
stats.dom.style.top = '50px'
const statsRef = ref(null)
const containerRef = ref(null)

// 创建一个场景
const scene = new Scene()

// 创建三维坐标轴,参数为坐标轴的大小，一般比物体的大就行了
const axesHelper = new AxesHelper(200)
// 将三维坐标添加到场景中
scene.add(axesHelper)



//  设置光源 参数一表示灯光颜色，参数二表示光照强度
const pointLight = new PointLight(0xffffff, 1.0);
// 设置为0则表示光照强度不受距离的影响
pointLight.decay = 0.0
// 设置灯光的位置
pointLight.position.set(400, 200, 150);
scene.add(pointLight);

// 环境光
const light = new AmbientLight(0xffffff); // 柔和的白光
scene.add(light);

// 平行光
// 从上方照射的白色平行光，强度为 0.5。
const directionalLight = new DirectionalLight(0xffffff, 0.5);
// 设置观察位置坐标，也就是说光源照射到哪个坐标点上
directionalLight.position.set(30, 30, 0)
scene.add(directionalLight);

const meshList = []
for (let index = 0; index < 10; index++) {
    for (let j = 0; j < 10; j++) {
        // 创建一个几何体
        const geometry = new BoxGeometry(100, 100, 100);

        // 定义一个材质color材质的颜色
        const material = new MeshLambertMaterial({
            color: 0x00ffff, // 材质的颜色
            transparent: true,
            opacity: 0.5
        });
        // 创建一个网格模型用于渲染几何体跟材质，为几何体添加一个材质
        const mesh = new Mesh(geometry, material);
        mesh.name = index + '-' + j
        // 设置网格模型的位置,其实就是物体放置相对模型的位置
        mesh.position.set(index * 200, 0, j * 200)
        meshList.push(mesh)
        // 将材质添加到场景中
        scene.add(mesh);

    }

}

// 创建一个透视投影相机对象
const width = ref(window.innerWidth)
const height = ref(window.innerHeight)
// const camera = new PerspectiveCamera(45, width.value / height.value, 1, 3000);
const camera = new PerspectiveCamera(45, width.value / height.value, 1, 10000);
// 设置相机的位置
// camera.position.set(200, 200, 200)
camera.position.set(2000, 2000, 2000)
// 定义相机的视线（观察目标）,也就是相机对准哪个点去观察拍照的意思
// camera.lookAt(0, 0, 0)
camera.lookAt(1000, 0, 1000)
// // 也可以直接指向网格模型的位置
// camera.lookAt(cube.position)

// 将相机添加到场景中
scene.add(camera);

// 创建一个渲染器
const renderer = new WebGLRenderer()
// 设置渲染器画布的大小，一般为相机的宽高比
renderer.setSize(width.value, height.value)
// 设置渲染哪个场景中的哪个相机，参数一为场景，参数二维相机
renderer.render(scene, camera)  // 类型相机的拍照动作，咔！！！

// 设置鼠标可操作，参数一为相机，参数二维渲染器的元素
const controls = new OrbitControls(camera, renderer.domElement)
// 重新更新相机的lookAt,set(1000, 0, 1000)为相机lookAt的值
controls.target.set(1000, 0, 1000)
controls.update()
// 监听是否发生变化，如果发生变化则重新渲染，渲染器
controls.addEventListener('change', function () {
    // 重新渲染器渲染器
    renderer.render(scene, camera)
})

// 查找几何体
const mesh12 = scene.getObjectByName('0-0');
console.log('aaaaaaaaa', mesh12)
// 创建后处理对象EffectComposer，WebGL渲染器作为参数，是一个渲染器
const composer = new EffectComposer(renderer);
// 创建一个渲染器通道，参数一场景，参数二相机作为参数
const renderPass = new RenderPass(scene, camera);
// 设置renderPass通道
composer.addPass(renderPass);
// OutlinePass第一个参数v2的尺寸和canvas画布保持一致
const v2 = new Vector2(window.innerWidth, window.innerHeight);
// const v2 = new THREE.Vector2(800, 600);
const outlinePass = new OutlinePass(v2, scene, camera);
// 一个模型对象
outlinePass.selectedObjects = [mesh12];
// // 多个模型对象
// outlinePass.selectedObjects = [mesh1];
// 设置OutlinePass通道
composer.addPass(outlinePass);

function render() {
    // 渲染处理效果，注意一定要注释掉次方法renderer.render(scene, camera)，或者放到前面
    composer.render();
    // 性能监控end==================================>性能监控
    stats.update()
    // 重新渲染渲染器
    // renderer.render(scene, camera)
    // 启动动画自动加载
    requestAnimationFrame(render)
}
render()

onMounted(() => {
    // 性能监控end==================================>性能监控
    statsRef.value?.appendChild(stats.dom)
    // 性能监控end==================================>性能监控
    // 将渲染出来的容器放入到页面中（意思是将renderer.domElement元素渲染到页面中的containerRef元素中） 
    containerRef.value?.appendChild(renderer.domElement)


})

// 监听窗口变化
window.addEventListener('resize', () => {
    // 设置渲染器大小
    renderer.setSize(window.innerWidth, window.innerHeight)
    // // 设置相机宽高比
    camera.aspect = window.innerWidth / window.innerHeight
    // 相机属性变化需要执行updateProjectionMatrix方法
    camera.updateProjectionMatrix()
}, false)

addEventListener('click', (e) => {
    // 获取鼠标点击坐标
    const px = e.offsetX
    const py = e.offsetY
    console.log("zzzzz", px, py)
    //屏幕坐标px、py转WebGL标准设备坐标x、y
    //width、height表示canvas画布宽高度
    const x = (px / width.value) * 2 - 1;
    const y = -(py / height.value) * 2 + 1;
    console.log("sssss", x, y)
    // 创建一个涉嫌投射器
    const raycaster = new Raycaster();
    raycaster.setFromCamera(new Vector2(x, y), camera)
    // 打印可以选择的模型
    console.log(meshList)
    const intersects = raycaster.intersectObjects(meshList)
    // 打印选择穿透的模型
    console.log(intersects)
    if (intersects.length > 0) {
        // 设置穿透的第一个模型的颜色
        intersects[0].object.material.color.set(0xff0000);
    }
})
onActivated(() => {

})


</script>

<style lang='less' scoped>
.container {
    height: 100%;
    width: 100%;
    margin: 0px;
    overflow: hidden;
}
</style>